package com.zmx.core.client.auth;

import com.zmx.core.dto.ChannelInfo;
import com.zmx.core.dto.HeartInfo;
import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.http.*;
import io.netty.util.CharsetUtil;
import lombok.extern.slf4j.Slf4j;
import oshi.SystemInfo;
import oshi.hardware.CentralProcessor;
import oshi.hardware.GlobalMemory;

import java.text.DecimalFormat;
import java.util.Date;

/**
 * @Description: 心跳监测
 * @ClassName: HeartTask
 * @Author zhaomxr
 * @Date 2021-12-14 15:51
 */
@Slf4j
public class HeartTask implements Runnable {

    //持有引用,方便读写操做
    private ChannelHandlerContext ctx;

    private HeartInfo heartInfo = new HeartInfo();

    public HeartTask(ChannelHandlerContext ctx, String ip, int port) {
        this.ctx = ctx;
        heartInfo.setIp(ip);
        heartInfo.setPort(port);
    }

    @Override
    public void run() {
        try {
            //获取系统内存等信息
            SystemInfo systemInfo = new SystemInfo();
            GlobalMemory memory = systemInfo.getHardware().getMemory();
            //总内存
            long totalByte = memory.getTotal();
            //剩余
            long acaliableByte = memory.getAvailable();

            //内存使用信息memory
            heartInfo.getMemInfo().put("total", formatByte(totalByte));
            heartInfo.getMemInfo().put("used", formatByte(totalByte - acaliableByte));
            heartInfo.getMemInfo().put("free", formatByte(acaliableByte));
            heartInfo.getMemInfo().put("usedRate", new DecimalFormat("#.##").format((totalByte - acaliableByte) * 1.0 / totalByte));

            CentralProcessor processor = systemInfo.getHardware().getProcessor();
            long[] prevTicks = processor.getSystemCpuLoadTicks();
            long[] ticks = processor.getSystemCpuLoadTicks();
            long nice = ticks[CentralProcessor.TickType.NICE.getIndex()] - prevTicks[CentralProcessor.TickType.NICE.getIndex()];
            long irq = ticks[CentralProcessor.TickType.IRQ.getIndex()] - prevTicks[CentralProcessor.TickType.IRQ.getIndex()];
            long softirq = ticks[CentralProcessor.TickType.SOFTIRQ.getIndex()] - prevTicks[CentralProcessor.TickType.SOFTIRQ.getIndex()];
            long steal = ticks[CentralProcessor.TickType.STEAL.getIndex()] - prevTicks[CentralProcessor.TickType.STEAL.getIndex()];
            long cSys = ticks[CentralProcessor.TickType.SYSTEM.getIndex()] - prevTicks[CentralProcessor.TickType.SYSTEM.getIndex()];
            long user = ticks[CentralProcessor.TickType.USER.getIndex()] - prevTicks[CentralProcessor.TickType.USER.getIndex()];
            long iowait = ticks[CentralProcessor.TickType.IOWAIT.getIndex()] - prevTicks[CentralProcessor.TickType.IOWAIT.getIndex()];
            long idle = ticks[CentralProcessor.TickType.IDLE.getIndex()] - prevTicks[CentralProcessor.TickType.IDLE.getIndex()];
            long totalCpu = user + nice + cSys + idle + iowait + irq + softirq + steal;
            //CPU使用信息

            //cpu系统使用率
            heartInfo.getCpuInfo().put("sysUsedRate", cpuUesdRate(cSys, totalCpu));
            //cpu系统使用率
            heartInfo.getCpuInfo().put("userUsedRate", cpuUesdRate(user, totalCpu));
            //cpu当前等待率
            heartInfo.getCpuInfo().put("waitUsedRate", cpuUesdRate(iowait, totalCpu));
            //cpu当前使用率
            heartInfo.getCpuInfo().put("idleUsedRate", totalCpu == 0 ? "0" : new DecimalFormat("#.##").format(1.0 - (idle * 1.0 / totalCpu)));

            heartInfo.setLasttime(new Date());

            ChannelInfo channelInfoR = new ChannelInfo("heart", heartInfo);
            ctx.writeAndFlush(channelInfoR);
        } catch (Exception e) {
            ctx.close();
            log.info("heart to server {} fail!");
        }
    }

    public static String formatByte(long byteNumber) {
        //换算单位
        double FORMAT = 1024.0;
        double kbNumber = byteNumber / FORMAT;
//        if (kbNumber < FORMAT) {
//            return new DecimalFormat("#.##KB").format(kbNumber);
//        }
        double mbNumber = kbNumber / FORMAT;
        if (mbNumber < FORMAT) {
            return new DecimalFormat("#.##MB").format(mbNumber);
        }
        double gbNumber = mbNumber / FORMAT;
        if (gbNumber < FORMAT) {
            return new DecimalFormat("#.##GB").format(gbNumber);
        }
        double tbNumber = gbNumber / FORMAT;
        return new DecimalFormat("#.##TB").format(tbNumber);
    }

    private static String cpuUesdRate(double number, long sum) {
        if (number == 0 || sum == 0) {
            return "0";
        }
        return new DecimalFormat("#.##").format(number * 1.0 / sum);
    }
}
